// CharCreatorPlugin.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "CharCreatorPlugin.h"
#include "..\Shared\ObjectManager.h"

__declspec(dllexport) IPlugin* __stdcall CreateInstance()
{
	return (IPlugin*)new CharCreatorPlugin();
}

__declspec(dllexport) int __stdcall GetInterfaceVersion(void)
{
	return PluginInterfaceVersion;
}

CharCreatorPlugin::CharCreatorPlugin()
{
	m_ModuleInfo.pluginName = "CharCreatorPlugin";
	m_ModuleInfo.author = "Craig Lynch";
	m_ModuleInfo.version = 0x00000001; // 0xMMmmaabb   MM = Major mm = Minor aa = Macro bb = Build
	m_ModuleInfo.numOfCommands = 9;
	m_ModuleInfo.commands[0] = "StartCharCreation";
	m_ModuleInfo.commands[1] = "ChangeStat";
	m_ModuleInfo.commands[2] = "GetStat";
	m_ModuleInfo.commands[3] = "GetAbilityPoints";
	m_ModuleInfo.commands[4] = "SetRace";
	m_ModuleInfo.commands[5] = "SetClass";
	m_ModuleInfo.commands[6] = "SetName";
	m_ModuleInfo.commands[7] = "InstantiateChar";
	m_ModuleInfo.commands[8] = "AutoAssignPoints";
	CreateChar = NULL;
}

bool __stdcall CharCreatorPlugin::HandleCommand(Command &NewCommand)
{
	bool Found = false;
	for(int i = 0; i < m_ModuleInfo.numOfCommands; i++)
	{
		if(m_ModuleInfo.commands[i] == NewCommand.name)
		{
			Found = true;
			break;
		}
	}
	if(!Found)
		return false;
	if(NewCommand.name == "StartCharCreation")
	{
		CharCreator *OldChar = CreateChar;
		CreateChar = new CharCreator;
		if(!CreateChar)
		{
			CreateChar = OldChar;
			NewCommand.Returns.Add(Value("Error", "Could not create new CharCreator."));
			return true;
		}
		delete OldChar;
		NewCommand.Returns.Add(Value("Result", "Created new CharCreator"));
		return true;
	}
	else if(NewCommand.name == "ChangeStat")
	{
		if(!CheckValid(NewCommand, 2))
		{
			NewCommand.Returns.Add(Value("Error", "Need a stat to change and whether or not to increase."));
			return true;
		}
		if(NewCommand.Arguments[0] == "Str")
		{
			if(NewCommand.Arguments[1] == "True")
				NewCommand.Returns.Add(Value("Result", CreateChar->changeStr(true)));
			else
				NewCommand.Returns.Add(Value("Result", CreateChar->changeStr(false)));
		}
		else if(NewCommand.Arguments[0] == "Dex")
		{
			if(NewCommand.Arguments[1] == "True")
				NewCommand.Returns.Add(Value("Result", CreateChar->changeDex(true)));
			else
				NewCommand.Returns.Add(Value("Result", CreateChar->changeDex(false)));
		}
		else if(NewCommand.Arguments[0] == "Con")
		{
			if(NewCommand.Arguments[1] == "True")
				NewCommand.Returns.Add(Value("Result", CreateChar->changeCon(true)));
			else
				NewCommand.Returns.Add(Value("Result", CreateChar->changeCon(false)));
		}
		else if(NewCommand.Arguments[0] == "Int")
		{
			if (NewCommand.Arguments[1] == "True")
				NewCommand.Returns.Add(Value("Result", CreateChar->changeInt(true)));
			else
				NewCommand.Returns.Add(Value("Result", CreateChar->changeInt(false)));
		}
		else if(NewCommand.Arguments[0] == "Wis")
		{
			if (NewCommand.Arguments[1] == "True")
				NewCommand.Arguments.Add(Value("Result", CreateChar->changeWis(true)));
			else
				NewCommand.Arguments.Add(Value("Result", CreateChar->changeWis(false)));
		}
		else if (NewCommand.Arguments[0] == "Cha")
		{
			if (NewCommand.Arguments[1] == "True")
				NewCommand.Arguments.Add(Value("Result", CreateChar->changeCha(true)));
			else
				NewCommand.Arguments.Add(Value("Result", CreateChar->changeCha(false)));
		}
		else
		{
			NewCommand.Arguments.Add(Value("Error", "You must specify a statistic to add to! (Str, Dex, Con, Wis, Int, Cha)"));
		}
		return true;
	}
	else if(NewCommand.name == "GetStat")
	{
		if(!CheckValid(NewCommand, 1))
		{
			NewCommand.Returns.Add(Value("Error", "Need stat to get."));
			return true;
		}
		if(NewCommand.Arguments[0] == "Str")
			NewCommand.Returns.Add(Value("Result", CreateChar->getStr()));
		else if(NewCommand.Arguments[0] == "Dex")
			NewCommand.Returns.Add(Value("Result", CreateChar->getDex()));
		else if (NewCommand.Arguments[0] == "Con")
			NewCommand.Returns.Add(Value("Result", CreateChar->getCon()));
		else if (NewCommand.Arguments[0] == "Wis")
			NewCommand.Returns.Add(Value("Result", CreateChar->getWis()));
		else if (NewCommand.Arguments[0] == "Int")
			NewCommand.Arguments.Add(Value("Result", CreateChar->getInt()));
		else if (NewCommand.Arguments[0] == "Cha")
			NewCommand.Arguments.Add(Value("Result", CreateChar->getCha()));
		else NewCommand.Arguments.Add(Value("Error", "You must specify a statistic to get! (Str, Dex, Con, Wis, Int, Cha)"));
		return true;
	}
	else if(NewCommand.name == "GetAbilityPoints")
	{
		if(!CreateChar)
		{
			NewCommand.Returns.Add(Value("Error", "Need to use StartCharCreation before changing stats."));
			return true;
		}

		NewCommand.Returns.Add(Value("Result", CreateChar->getAbilityPoints()));
		return true;
	}
	else if(NewCommand.name == "SetRace")
	{
		if(!CheckValid(NewCommand,1))
		{
			NewCommand.Returns.Add(Value("Error", "Need a race name to set race to."));
		}
		NewCommand.Returns.Add(Value("Result", CreateChar->setRace((char *)NewCommand.Arguments[0].ToCharPtr())));
		return true;
	}
	else if(NewCommand.name == "SetClass")
	{
		if(!CheckValid(NewCommand,1))
		{
			NewCommand.Returns.Add(Value("Error", "Need a class name to set class to."));
		}
		NewCommand.Returns.Add(Value("Result", CreateChar->setClass((char *)NewCommand.Arguments[0].ToCharPtr())));
		return true;
	}
	else if(NewCommand.name == "SetName")
	{
		if(!CheckValid(NewCommand,1))
		{
			NewCommand.Returns.Add(Value("Error", "Need a race name to set race to."));
			return true;
		}
		CreateChar->setName((char *)NewCommand.Arguments[0].ToCharPtr());
		NewCommand.Returns.Add(Value("Result", ""));
		return true;
	}
	else if(NewCommand.name == "InstantiateChar")
	{
		if (!CheckValid(NewCommand,1))
		{
			NewCommand.Returns.Add(Value("Error", "Need to pass true or false value to check whether player is a PC or not"));
			return true;
		}
		if((NewCommand.Arguments[0] != "True")&&(NewCommand.Arguments[0] != "False"))
		{
			NewCommand.Returns.Add(Value("Error", "Need to pass True or False value to check whether player is a PC or not"));
			return true;
		}  
		Character *InstChar = CreateChar->instantiate();
		if (!InstChar->isvalid())
		{
			NewCommand.Returns.Add(Value("Error", InstChar->getState()));
			delete InstChar;
			return true;
		}
		m_Objects->AddObject();
		Object &NewChar = (*m_Objects)[m_Objects->GetSize()-1];
		Value &CharName = NewChar.GetBaseAttribute("Name");
		CharName = InstChar->getName();
		m_Objects->AddAttributeToObject(CharName,Value("Str", InstChar->getStr()));
		m_Objects->AddAttributeToObject(CharName,Value("Dex", InstChar->getDex()));
		m_Objects->AddAttributeToObject(CharName,Value("Con", InstChar->getCon()));
		m_Objects->AddAttributeToObject(CharName,Value("Int", InstChar->getInt()));
		m_Objects->AddAttributeToObject(CharName,Value("Wis", InstChar->getWis()));
		m_Objects->AddAttributeToObject(CharName,Value("Cha", InstChar->getCha()));
		m_Objects->AddAttributeToObject(CharName,Value("Race", InstChar->getRace()));
		m_Objects->AddAttributeToObject(CharName,Value("Class", InstChar->getClass()));
		m_Objects->AddAttributeToObject(CharName,Value("Speed", InstChar->getSpeed()));
		m_Objects->AddAttributeToObject(CharName,Value("XP", InstChar->getXP()));
		m_Objects->AddAttributeToObject(CharName,Value("Level", InstChar->getLevel()));
		m_Objects->AddAttributeToObject(CharName,Value("CurHP", InstChar->getCurHP()));
		m_Objects->AddAttributeToObject(CharName,Value("MaxHP", InstChar->getMaxHP()));
		m_Objects->AddAttributeToObject(CharName,Value("AC", InstChar->getAC()));
		m_Objects->AddAttributeToObject(CharName,Value("Initiative", InstChar->getInit()));
		m_Objects->AddAttributeToObject(CharName,Value("FortSave", InstChar->getFortSave()));
		m_Objects->AddAttributeToObject(CharName,Value("WillSave", InstChar->getWillSave()));
		m_Objects->AddAttributeToObject(CharName,Value("ReflexSave", InstChar->getReflexSave()));
		m_Objects->AddAttributeToObject(CharName,Value("BaseAtkBonus", InstChar->getBaseAtkBonus()));
		m_Objects->AddAttributeToObject(CharName,Value("PC", NewCommand.Arguments[0].ToCharPtr()));
		m_Objects->AddAttributeToObject(CharName,Value("PASSABLE", 2));

		m_Objects->AddObject();
		Object &newEquipment = (*m_Objects)[m_Objects->GetSize()-1];
		Value &charEquipment = newEquipment.GetBaseAttribute("Name");
		charEquipment = "Equipped";
		m_Objects->AddAttributeToObject(charEquipment,Value("Head", -1));
		m_Objects->AddAttributeToObject(charEquipment,Value("RHand",-1));
		m_Objects->AddAttributeToObject(charEquipment,Value("LHand",-1));
		m_Objects->AddAttributeToObject(charEquipment,Value("Feet",-1));
		m_Objects->AddAttributeToObject(charEquipment,Value("Chest",-1));
		m_Objects->AddChildToObject(InstChar->getName(), newEquipment.GetIndex());
				
		delete InstChar;
		return true;
	}
	else if (NewCommand.name == "AutoAssignPoints")
	{
	if(!CreateChar)
	{
		NewCommand.Returns.Add(Value("Error", "Need to use StartCharCreation before using this module."));
		return false;
	}
		CreateChar->autoAssignPoints();
		return true;
	}
	return false;
}

bool CharCreatorPlugin::CheckValid(Command &NewCommand, int numberOfArguments)
{
	if(!CreateChar)
	{
		NewCommand.Returns.Add(Value("Error", "Need to use StartCharCreation before using this module."));
		return false;
	}
	if(NewCommand.Arguments.Size() != numberOfArguments)
	{
		return false;
	}

	return true;
}